function JEdit(owner, parent, name, dataset, field, rect, type, tab, tabStop, tabIndex, richText, flags)
{
	var self = this,
	    _richText = utils.parseBool(richText),
	    _richTextReadOnly,
	    _richTextInstance = null,
	    _richTextHideTimeout,
	    _richTextOnKeyPress = null,
		_richTextOnMouseDown = null,
		_richTextOnChange = null,
	    _disposed = false,
	    _saveCheckTimer = null,
	    _settingValue = false,
	    _events = [],
	    _form,
	    _isDirty,
	    _isNoData = false,
	    _isReadOnly = false,
	    _elem = null;
	

	this.initialize(owner, parent, name, null, null, rect, flags, field, dataset, tab);

	this.value    = null;
	this.type     = new Number(type);
	this.controlType = 'text';
	this.interval = null;
	this.step     = 1;
	this.methods  = (cmRender | cmLoad | cmSave);
	this.child    = null;
	this.dirty    = false;
	this.orgValue = null;
	this.tabStop  = tabStop;
	this.tabIndex = (tabIndex == null) ? -1 : parseInt(tabIndex);

	this.owner.addImage("remote-edit", "remote-edit.gif", "controls");
	this.owner.addImage("spinner-edit", "spinner-edit.gif", "controls");

	this.bind_setValue  = bind_setValue;
//	this.setIsNoData = setIsNoData;
//	this.setIsReadOnly = setIsReadOnly;

//	this.isDirty	= isDirty;

	this.render     = render;
	this.load       = load;
	this.keyHandler = keyHandler;
	this.click      = click;
	this.setFocus   = setFocus;
	this.dispose	= dispose;

	_form = this.getForm();

	if (self.type == etSimple)
		self.type = etRemote;

	function render(fs)
	{
		var localFs = false;
		if (!fs)
		{
			fs = new FastString();
			localFs = true;
		}

		var readOnly = false;
		var addClass = '';

		if (self.dataset != null)
		{
			readOnly = self.dataset.isReadOnly(self.field);
			self.controlType = 'text';

			if ((self.dataset.fields[self.field] != null) && (utils.inSet(ffPassword, self.dataset.fields[self.field].flags)))
				self.controlType = 'password';

			if (self.isInvisible())
			{
				addClass += ' invisible';
			}
		}


		if (_richText)
		{
			fs.append('<div id="' + self.name + '_toolbar" style="z-index: 1000;"></div>');
		}

		if (self.type == etSimple)
		{
			fs.append('<input class="edit' + addClass + '" type="' + self.controlType + '" id="' + self.name + '" value="" />');
		}
		else
		if (self.type == etMemo)
		{
			fs.append('<textarea class="edit' + addClass + '" id="' + self.name + '" name="' + self.name + '"></textarea>');
		}
		else
		if (self.type == etRemote)
		{
			fs.append('<input class="editRemote' + addClass + '" type="' + self.controlType + '" id="' + self.name + '" />');
			if (!readOnly)
			{
				fs.append('<img class="editImg' + addClass + '" id="' + self.name + '_remoteImg" src="' + self.owner.images['remote-edit'].src + '"/>');
			}
		}
		else
		if (self.type == etSpinner)
		{
			fs.append('<input class="edit' + addClass + '" type="text" id="' + self.name + '" name="' + self.name + '" />');
			if (!readOnly)
			{
				fs.append('<img class="editImg' + addClass + '" id="' + self.name + '"_spinImg" src="' + self.owner.images['spinner-edit'].src + '">');
			}
		}

		if (localFs)
			return (fs.toString());
	}
	
	function load()
	{
		if (self.isInvisible())
			return;

		var readOnly = false,
			elem = self.$$(),
			img = null,
			corr = 0;

		if (self.dataset != null)
			readOnly = self.dataset.isReadOnly(self.field);

		elem.tabIndex = self.tabIndex;
		if (_form.setActiveControl)
			elem.onfocus = function() { _form.setActiveControl(self); };

		if (self.type == etRemote)
		{
			if (!readOnly)
			{
				img = self.$$('_remoteImg');
				if (img != null)
				{ 
					img.onclick = self.click;
					corr = 17;
				}
			}

//			elem.onkeydown = self.keyHandler;
		}
		else
		if (self.type == etSpinner)
		{
			if (!readOnly)
			{
				img = self.$$('_spinImg');
				if (img != null)
				{
					img.onclick = self.click;
					elem.onkeydown = self.keyHandler;
					corr = 17;
				}
			}
		}

		if (self.dataset != null)
			self.value = utils.coalesce(self.dataset.get(self.field), '');

		self.orgValue = self.value;
		elem.value = self.value;

		if (readOnly)
		{
			elem.readOnly = true;
			elem.onkeydown = self.keyHandler;
			elem.className += ' editReadOnly';
		}
		else
		{
			elem.onchange = function()
			{
				self.value = this.value;
				checkChanged();
			};

			elem.onkeyup = function()
			{
			    checkChanged();
			};
		}

		setStyles(elem, img, corr);

		if (self.dataset != null) 
		{
			if (! _richText)
			{
				self.dataset.bindingManager.bind(elem, 'value', self.field, true, self);
				_elem = elem;
			}
		}

		if (_richText)
		{
			var doc = self.owner.getDocument();
            
/*
            var btn = doc.createElement('input');
            btn.type = 'button';
            btn.value = 'upload';
            btn.onclick = function()
            {
				var query = new Postback();
				query.set("act", "eblob");
				query.set("newAct", "setRTImage");
				query.set("cid", self.owner.session);
				query.set("afm", self.owner.activeForm.name);
				query.set("obj", self.dataset.name);
				query.set("rec", self.dataset.getCurrentRecord().key);
				query.set("fid", self.field);

				window.open(self.owner.cgiPath() + '?' + query.toString(), "", "width=370,height=100,location=no,menubar=no,resizable=no,scrollbars=no,status=yes");
            }
            
            self.$$().parentNode.appendChild(btn);
*/
			addRichTextEditor();

		}

		checkControlState();
	}

	function setStyles(elem, img, corr)
	{
		var style = elem.style;

		if (self.inplace)
		{
			var prnt = elem.parentNode;

			var orgClassName = elem.className;
			elem.className = 'editInplace';
			if (orgClassName.indexOf('editReadOnly') > -1)
				elem.className += ' editReadOnly';
			if ((orgClassName.indexOf('requiredField') > -1) && (elem.className.indexOf('editReadOnly') == -1))
				elem.className += ' requiredField';

			style.height = prnt.clientHeight - 2;
			style.width = prnt.clientWidth - corr - 4;
			//style.fontSize = prnt.clientHeight - 8;
			style.textAlign = prnt.style.textAlign;
			prnt.style.textAlign = '';
		}
		else
		{
			style.position = (self.rect.isRelative()) ? 'relative' : 'absolute';
			style.top = self.rect.top;
			style.left = self.rect.left;
			style.height = self.rect.height;
			style.width = self.rect.width - corr;

			if (img != null)
			{
				var s = img.style;
				s.left = self.rect.left + self.rect.width - corr;
				s.top = self.rect.top + 2;
			}
		}
	}
	
	function _ufirst(s)
	{
		return s.substring(0, 1).toUpperCase() + s.substring(1);
	}

	function addRichTextEditor()
	{
		
		var PrepareRichTextEditor = function(){
			initRichTextEditor(editorInstance);
			self.dataset.bindingManager.bind(self, 'value', self.field, true);

			var toolbar = self.$$('_external');
			var edParent = self.$$('_parent');
			var iframe = self.$$('_ifr');
			edParent.tabIndex = self.$$().tabIndex;

			var DOM = tinymce.DOM;
			DOM.setStyle(edParent, 'position', 'absolute');
			DOM.setStyle(edParent, 'top', self.rect.top);
			DOM.setStyle(edParent, 'height', self.rect.height);
			DOM.setStyle(edParent, 'left', self.rect.left);

			if (toolbar != null)
			{
				var tParent = toolbar.parentNode;
				var s = editorInstance.settings;
				tParent.className = s.skin + 'Skin' + (s.skin_variant ? ' ' + s.skin + 'Skin' + _ufirst(s.skin_variant) : '');
				DOM.setStyle(tParent, 'z-index', 1000);
				self.$$('_toolbar').appendChild(tParent.parentNode.removeChild(tParent));

				if (!self.getForm().loaded){
					self.getForm().onload.attach(setToolboxEvents);
				} else {
					setToolboxEvents();
				}
				
				DOM.setStyle(tParent, 'position', 'absolute');
 				DOM.setStyle(tParent, 'top', parseInt(self.rect.top) - 54 + 'px');
				DOM.setStyle(tParent, 'left', self.rect.left + 'px');
				
			}

			editorInstance.isDirty = function()
			{
				var t = this;
				return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'html', no_events : 0 })) && !t.isNotDirty;
			};
			
			

			if (! readOnly)
			{
				var userDidSomething = true;
				editorInstance.onKeyPress.add(_richTextOnKeyPress = function(){
					userDidSomething = true;
				});
				
				editorInstance.onMouseDown.add(_richTextOnMouseDown = function(){
					userDidSomething = true;
				});
				
				editorInstance.onChange.add(_richTextOnChange = function(){
					userDidSomething = true;
				})
				
//				editorInstance.onNodeChange.add(_richTextOnChange = function(ed, l)

				_saveCheckTimer = self.owner.getWindow().setInterval(function()
				{
					if (_form.activeControl !== self)
						return;
						
					if (!userDidSomething) {
						return
					} else {
						userDidSomething = false;
					}

					if (editorInstance.isDirty())
					{
						self.value = editorInstance.getContent();
						if (self.value != self.orgValue)
						{
							self.$$().value = self.value;
							_settingValue = true;
							try
							{
								self.dataset.getCurrentRecord().setValue(self.field, self.value);
							}
							finally
							{
								_settingValue = false;
							}

							_isDirty = true;
							_form.setSaveButton(true);
						}
						else
						{
							_form.checkSaveButton(self);
							_isDirty = false;
						}
					}
					else
					{
						_form.checkSaveButton(self);
						_isDirty = false;
					}

//					checkChanged();
				}, 2000);

			}
		}
		
		var readOnly = false,
			elem = self.$$();

		if (self.dataset != null)
			readOnly = self.dataset.isReadOnly(self.field);
		_richTextReadOnly = readOnly;

		if ((typeof(tinyMCE) != 'undefined') && (tinyMCE != null))
		{
			elem.value = utils.coalesce(getFieldValue(), '');

			var editorInstance = _richTextInstance = new tinymce.Editor(self.name, tinyMCE.settings);
			editorInstance.settings.readonly = readOnly;
			editorInstance.render();

			if (! editorInstance.initialized)
			{
				editorInstance.onInit.add(function()
				{
					editorInstance.onInit.remove(arguments.callee);
					PrepareRichTextEditor();
				});
			}
			else
			{
				PrepareRichTextEditor();
			}
		}
	 }

	function setToolboxEvents()
	{
		self.getForm().onload.detach(setToolboxEvents);
//		self.getForm().$$().focus();
		var ctrls = null, minTabIndex = 999999, idx = -1, prnt = self.getParentObject();
		
		if (self.tab != null)
		{
			if (prnt.active == self.tab)
				ctrls = prnt.getTabControls(self.tab);
		}
		else
		{
			ctrls = prnt.controls;
		}

  		if ((ctrls != null) && (ctrls.length) && (ctrls.length > 0))
		{
			for (var i = 0; i < ctrls.length; i++)
			{
				if ((ctrls[i].constructor == JEdit) && (ctrls[i].tabIndex < minTabIndex))
				{
					minTabIndex = ctrls[i].tabIndex;
					idx = i;
				}
			}

			if (idx > -1)
				try
				{
					ctrls[idx].$$().focus();
				}
				catch(ex)
				{}
		}

		_richTextHideTimeout = null;

		var toolbar = self.$$('_external');
		var iframe = self.$$('_ifr');
		var DOM = tinymce.DOM;


		if (browser.isIE)
		{
			self.owner.getWindow().setTimeout(function()
			{
				var f1 = tinymce.dom.Event.add(iframe, 'focus', function(e)
				{
					_form.setActiveControl(self);
					_richTextInstance.theme.showToolbox();
					DOM.setStyle(toolbar, 'top', '0px');
				});
				_events.push({obj: iframe, name: 'focus', fn: f1});
			}, 200);

			var f2 = tinymce.dom.Event.add(iframe, 'blur', function()
			{
				_richTextHideTimeout = self.owner.getWindow().setTimeout(function() {
					_richTextInstance.theme.hideToolbox();
				}, 300);
			});

			_events.push({obj: iframe, name: 'blur', fn: f2});
		}
		else
		{
			var doc = _richTextInstance.getDoc();
			if (browser.isWebKit)
				doc = doc.body;
			else
			if (browser.isOpera)
				doc = _richTextInstance.getWin();

			self.owner.getWindow().setTimeout(function()
			{
				var f1 = tinymce.dom.Event.add(doc, 'focus', function()
				{
					_form.setActiveControl(self);
					_richTextInstance.theme.showToolbox();
					DOM.setStyle(toolbar, 'top', '0px');
				});
				_events.push({obj: doc, name: 'focus', fn: f1});
			}, 200);

			var f2 = tinymce.dom.Event.add(doc, 'blur', function()
			{
				_richTextHideTimeout = self.owner.getWindow().setTimeout(function() { _richTextInstance.theme.hideToolbox(); }, 300);
			});

			_events.push({obj: doc, name: 'blur', fn: f2});
		}


		var fclick = tinymce.dom.Event.add(toolbar, 'click', function(e)
		{
			if (_richTextHideTimeout != null)
			{
				self.owner.getWindow().clearTimeout(_richTextHideTimeout);
				_richTextHideTimeout = null;
			}

		});

		_events.push({obj: toolbar, name: 'click', fn: fclick});
	}

	function initRichTextEditor(editorInstance)
	{
		self.bind_setValue('value', null, null);
	}

	function getFieldValue()
	{
		var record = self.dataset.getCurrentRecord();
		var	value = (record) ? record.getText(field) : '';
		if ((_richText) && (value) && (value.length > 0))
			return value.replace(/@ICPATH@/g, self.owner.cgiPath() + '?act=' + raActionNames[raGetRichTextImage] +
								 '&cid=' + self.owner.session +
								 '&afm=' + self.getForm().name +
								 '&acl=' + self.name +
								 '&ads=' + self.dataset.name +
								 '&rec=' + record.key +
								 '&fld=' + self.field);

		return value;
	}

	function checkChanged()
	{
		if (_form.setSaveButton)
		{
//			if (self.value != self.orgValue)
			if (self.$$().value != getFieldValue())
				_form.setSaveButton(true);
			else
			if (_form.checkSaveButton)
				_form.checkSaveButton(self);
		}
	}

	function getEditorValue()
	{
		if (_richText)
		{
			return tinyMCE.get(self.name).getContent();
		}
		else
		{
		    return self.$$().value;
		}
	}

	function bind_setValue(prop, field, record)
	{
		if (_disposed)
			return;
		
		if ((record) && (record.isNoData(field)))
			return;
		
		if (prop == 'value')
		{
			var value = utils.coalesce(getFieldValue(), '');
			if (_richText)
			{
				if (_settingValue)
					return;

				if (self.dataset != null)
					readOnly = self.dataset.isReadOnly(self.field);

				readOnly = readOnly | _isNoData | _isReadOnly;

				if (_richTextReadOnly != readOnly)
				{
					removeRichTextEditor();
					addRichTextEditor();
				}
				
				if (field && record)
				  record.setNewValue(field, value);
				
				if (! _richTextInstance.initialized)
				{
					_richTextInstance.onInit.add(function()
					{
						_richTextInstance.onInit.remove(arguments.callee);
						_richTextInstance.setContent(value);
						_richTextInstance.undoManager.clear();
						_richTextInstance.startContent = _richTextInstance.getContent({format : 'html', no_events : 0});
						self.orgValue = getEditorValue();
					});
				} else {
					_richTextInstance.setContent(value);
					_richTextInstance.undoManager.clear();
					_richTextInstance.startContent = _richTextInstance.getContent({format : 'html', no_events : 0});
					self.orgValue = getEditorValue();
				}

				if (_richTextHideTimeout != null)
				{
					self.owner.getWindow().clearTimeout(_richTextHideTimeout);
					_richTextHideTimeout = null;
				}
			}
			else
			{
			}
		}

		checkControlState(record);
	}

	function checkControlState(record)
	{
		if (self.isInvisible())
			return;

		var elem = self.$$();
		if (!elem)
			return;
		
		if (!record)
			record = self.dataset.getCurrentRecord();

		var noData = (record) && (record.isNoData(self.field));
		var readOnly = (record) && (record.isReadOnly(self.field));

		if ((noData) || (readOnly))
		{
			elem.readOnly = true;
			elem.onkeydown = self.keyHandler;
			if (elem.className.indexOf('editReadOnly') == -1)
				elem.className += ' editReadOnly';

			if ((self.type == etRemote) && (self.$$('_remoteImg') != null))
			{
				var style = self.$$('_remoteImg').style;

				style.display = 'none';
				style.visibility = 'hidden';
			}
			else
			if ((self.type == etSpinner) && (self.$$('_spinImg') != null))
			{
				var style = self.$$('_spinImg').style;
				style.display = 'none';
				style.visibility = 'hidden';
			}

		}
		else
		{
			elem.readOnly = false;
			
			elem.style.display = '';

			if (elem.className.indexOf('editReadOnly') > -1)
				elem.className = elem.className.replace('editReadOnly', '');

			if ((self.type == etRemote) && (self.$(self.name + '_remoteImg') != null))
			{
				var style = self.$$('_remoteImg').style;

				style.display = '';
				style.visibility = '';
			}
			else
			if ((self.type == etSpinner) && (self.$(self.name + '_spinImg') != null))
			{
				var style = self.$$('_spinImg').style;
				style.display = '';
				style.visibility = '';
			}
		}

		var required = (record) && (record.isRequired(self.field));
		if (required)
		{
			if ((elem.className.indexOf('requiredField') == -1) && (elem.className.indexOf('editReadOnly') == -1))
				elem.className += ' requiredField';
		}
		else
			elem.className = elem.className.replace(' requiredField', '');


		var isSelect = (record) && (record.isSelect(self.field));
		if ((self.type == etRemote) && (self.$$('_remoteImg') != null))
		{
			var img = self.$$('_remoteImg');
			if (isSelect)
			{
				if (! self.inplace)
					setStyles(elem, img, (readOnly) ? 0 : 17);
			}
			else
			{
				img.style.display = 'none';
				img.style.visibility = 'hidden';

				if (!self.inplace)
					setStyles(elem, null, 0);
			}
		}
	}

/*
	function setIsNoData(isNoData)
	{
		_isNoData = isNoData;
		checkControlState();
	}
	
	function setIsReadOnly(isReadOnly)
	{
		_isReadOnly = isReadOnly;
		checkControlState();
	}
*/
	
	function keyHandler(event)
	{
		if (browser.isIE)
			event = self.owner.getDocument().parentWindow.event;

		if ((!event.ctrlKey && utils.inList(event.keyCode, 9, 35, 36, 37, 39)) || (event.ctrlKey && utils.inList(event.keyCode, 67, 86)))
		{
			if (event.returnValue)
				event.returnValue = true;
		}
		else
		{
			if ((self.type == etRemote) && (utils.inList(event.keyCode, 8, 46)))
			{
				if ((self.dataset != null) && (! self.dataset.isReadOnly(self.field)))
				{
					self.dataset.set(self.field, null);
					self.value = utils.coalesce(self.dataset.get(self.field), '');
					self.orgValue = self.value;
				}
			}

			if (browser.isIE)
				event.returnValue = false;
			else
			if (event.preventDefault)
				event.preventDefault();
		}
	}
	
	function click()
	{
		_form.setActiveControl(self);

		if (self.dataset == null)
			return;

		if (self.type == etRemote)
		{
			// check if field is select
			// because this function can also be called with F4 button
			var record = self.dataset.getCurrentRecord();
			var isSelect = (record) && (record.isSelect(self.field));
			if (!isSelect)
				return;

			var query = new Postback();

			query.set('ads', self.dataset.name);
			query.set('obj', (self.inplace == true) ? self.parent : self.name);
			query.set('fid', self.field);

			if (!self.dataset.isEmpty())
			{
				var rec = self.dataset.getCurrentRecord();
				query.set('rec', rec.key);
				if (rec.isDirty())
					query.set('dat', escape(rec.toString()));
			}

			self.owner.post(raRemoteOpen, query);
		}
		else
		if (self.type == etSpinner)
		{
// TODO: toto je spatne, je potreba to nekde zkontrolovat 
			var event = self.owner.frame.event;
			var value = new Number(self.owner.frame.document.getElementById(self.name).value);
			if (!isNaN(value))
			{
				value += (event.offsetY < Math.round(event.srcElement.height / 2) ? 1 : -1) * self.step;
				if ((value >= self.interval.low) && (value <= self.interval.high))
					self.$$().value = value;
			}
//			self.save();
		}
	}

	function setFocus()
	{
	    try
	    {
			if (_richText)
			{
				
			    var ed = _richTextInstance;
				if (browser.isIE && (browser.version >= 11)){
					//ed.selection.select(ed.getBody(), 1); // this freezes IE11
					//ed.selection.collapse(1); // this freezes IE11
					ed.getWin().focus();
				} else {
					ed.selection.select(ed.getBody(), 1);
					ed.selection.collapse(1);
					ed.getWin().focus();
				}
			}
			else
		    {
				if (self.$$().focus)
					self.$$().focus();
			}
		}
		catch(ex)
		{}
	}
	

	function dispose()
	{
		if (_disposed)
			return;

		if (_saveCheckTimer != null)
			self.owner.getWindow().clearInterval(_saveCheckTimer);

		if (_richText)
		{
			removeRichTextEditor();
		}

		if ((_elem) && (self.dataset != null) && (self.dataset.bindingManager != null))
		{
			self.dataset.bindingManager.unbind(_elem, 'value');
		}

		var elem = self.$(self.name);
		if (elem != null)
		{
			elem.onfocus = null;

			elem.onchange = null;
			elem.onkeyup = null;
			elem.onkeydown = elem.onclick = null;
		}

		if ((self.type == etRemote) && (self.$(self.name + '_remoteImg') != null))
			self.$(self.name + '_remoteImg').onclick = null;
		else
		if ((self.type == etSpinner) && (self.$(self.name + '_spinImg') != null))
			self.$(self.name + '_spinImg').onclick = null;

		self.base.dispose.call(self);
		_disposed = true;
	}
	
	function removeRichTextEditor()
	{
		if ((typeof(tinyMCE) != 'undefined') && (tinyMCE != null))
		{
			try
			{
			    if ((_richTextInstance) && (_richTextInstance.theme))
					_richTextInstance.theme.hideToolbox();

				tinyMCE.execCommand('mceRemoveControl', false, self.name);
				removeTinyMCEEvents();
			}
			catch(ex)
			{}
		}
	}
	
	function removeTinyMCEEvents()
	{
		if ((self.dataset != null) && (self.dataset.bindingManager != null))
			self.dataset.bindingManager.unbind(self, 'value');

	    while (_events.length > 0)
	    {
			var evnt = _events.pop();
			if (evnt != null)
				tinymce.dom.Event.remove(evnt.obj, evnt.name, evnt.fn);
		}

		if (_richTextOnKeyPress != null)
			_richTextInstance.onKeyPress.remove(_richTextOnKeyPress);
			
		if (_richTextOnMouseDown != null)
			_richTextInstance.onMouseDown.remove(_richTextOnMouseDown);
			
		if (_richTextOnChange != null)
			_richTextInstance.onChange.remove(_richTextOnChange);

			
	}
}

JEdit.inheritsFrom(ControlBase);

if (typeof(loadNextScript) != 'undefined')
	loadNextScript();
